from lxml import etree
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

from crack_bili.img_helper import crop_img

browser = webdriver.Chrome()
# 设置浏览器窗口大小
browser.set_window_size(1400, 700)
# 设置隐世等待
wait = WebDriverWait(browser, 5)


def is_pixel_eq(capt1, capt2, x, y):
    c1 = capt1.load()[x, y]
    c2 = capt2.load()[x, y]
    # 判断阈值，颜色rgb差值<60，两个基本一致
    val = 60
    if abs(c1[0] - c2[0]) < val and abs(c1[1] - c2[1]) < val and abs(c1[2] - c2[2]) < val:
        return True
    return False


def get_gap_pos(capt1, capt2):
    """获取缺口坐标"""
    left = 90
    size = capt1.size
    # 横向纵向扫描像素，匹配颜色是否相等
    for x in range(left, size[0]):
        for y in range(size[1]):
            pixel_eq = is_pixel_eq(capt1, capt2, x, y)
            if not pixel_eq:
                return x
    return -1


def get_track(distance):
    """
    根据偏移量获取移动轨迹
    :param distance: 偏移量
    :return: 移动轨迹
    """
    # 移动轨迹
    track = []
    # 当前位移
    current = 0
    # 减速阈值
    mid = distance * 3 / 5
    # 计算间隔
    t = 0.7
    # 初速度
    v = 0
    distance += 14  # 滑超过一段距离

    while current < distance:
        if current < mid:
            # 加速度为正2
            a = 4
        else:
            # 加速度为负3
            a = -2
        # 初速度v0
        v0 = v
        # 当前速度v = v0 + at
        v = v0 + a * t
        # 移动距离x = v0t + 1/2 * a * t^2
        move = v0 * t + 1 / 2 * a * t * t
        # 当前位移
        current += move
        # 加入轨迹
        track.append(round(move))
    track[-1] = distance - sum(track[:-1])
    return track


def get_page():
    url = 'https://passport.bilibili.com/login'
    browser.get(url)

    # 用户名与密码
    inp = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#login-username')))
    inp.clear()
    inp.send_keys('carmack108\tpassword')

    # 密码
    # inp = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#login-passwd')))
    # inp.clear()
    # inp.send_keys('12345678')

    ok_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'a.btn.btn-login')))
    ok_btn.click()

    # 延时等验证图片，截图
    time.sleep(2)
    css = '.geetest_canvas_slice.geetest_absolute'
    img1 = 'captcha.png'
    capt1 = crop_img(browser, css, img1)

    # 修改css属性，显示隐藏图片
    str_js = 'var element = document.getElementsByClassName("geetest_canvas_fullbg geetest_fade geetest_absolute")[0];element.style.display="block";'
    browser.execute_script(str_js)
    time.sleep(2)
    img2 = 'captcha2.png'
    capt2 = crop_img(browser, css, img2)

    # 获取缺口位置
    x = get_gap_pos(capt1, capt2)
    print('x:', x)

    # 获取移动轨迹
    gap_len = x - 12  # 移动方块前面间隙为12
    move_list = get_track(gap_len)
    print('move list:', move_list)
    print('move list:', sum(move_list))

    slider_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'div.geetest_slider_button')))

    move_to_gap(slider_btn, move_list)
    # ActionChains(browser).click_and_hold(slider_btn).perform()
    # # 进行位移
    # for dist in move_list:
    #     ActionChains(browser).move_by_offset(xoffset=dist, yoffset=0).perform()
    # time.sleep(0.1)
    # ActionChains(browser).release().perform()


def shake_mouse():
    """
    模拟人手释放鼠标抖动
    :return: None
    """
    ActionChains(browser).move_by_offset(xoffset=-2, yoffset=0).perform()
    ActionChains(browser).move_by_offset(xoffset=3, yoffset=0).perform()


def move_to_gap(slider, tracks):
    """
    拖动滑块到缺口处
    :param slider: 滑块
    :param tracks: 轨迹
    :return:
    """
    back_tracks = [-1, -1, -2, -2, -3, -2, -2, -1, -1]
    ActionChains(browser).click_and_hold(slider).perform()
    for x in tracks:  # 正向
        ActionChains(browser).move_by_offset(xoffset=x, yoffset=0).perform()
    time.sleep(0.5)
    for x in back_tracks:  # 逆向
        ActionChains(browser).move_by_offset(xoffset=x, yoffset=0).perform()
    shake_mouse()
    time.sleep(0.5)
    ActionChains(browser).release().perform()


def main():
    """主函数"""
    get_page()


if __name__ == '__main__':
    main()
